package cn.wolfcode.luowowo.search.service.impl;

import cn.wolfcode.luowowo.search.domain.StrategyTemplate;
import cn.wolfcode.luowowo.search.query.StrategySearchQuery;
import cn.wolfcode.luowowo.search.repository.StrategyTemplateRepository;
import cn.wolfcode.luowowo.search.service.IStrategyEsService;
import cn.wolfcode.luowowo.search.vo.StatisVo;
import com.alibaba.dubbo.config.annotation.Service;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.InternalMultiBucketAggregation;
import org.elasticsearch.search.aggregations.bucket.composite.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;

import java.util.*;

@Service
public class StrategyEsServiceImpl implements IStrategyEsService {

    @Autowired
    private StrategyTemplateRepository repository;
    @Override
    public void save(StrategyTemplate template) {
        repository.save(template);

    }

    @Override
    public List<Map<String, Object>> queryThemeCommend() {

        List<Map<String,Object>> data = new ArrayList<>();

       List<StatisVo>list = this.getStatsVOList("themeId","themeName","themeGroup");

        //优化2  取前面10
        if (list.size()>10){
            list = (ArrayList<StatisVo>) list.subList(0,10);
        }




        //2 通过主题 id   themeId查询目的地集合
        Map<String,Object> map =null;
        for (StatisVo vo :list){
            map = new HashMap<>();
            map.put("theme",vo);
            //某个主题下关联的目的地集合
            List<StatisVo> dests = this.getDestByThemeId(vo.getId());
            map.put("dests",dests);
            data.add(map);
        }

        return data;
    }

    @Override
    public List<StatisVo> aueryConditionChina() {
        return this.getStatsVOList("provinceId","provinceName","provinceGroup");
    }

    @Override
    public List<StatisVo> aueryConditionAbroad() {
        return this.getStatsVOList("countryId","countryName","countryGroup");
    }

    @Override
    public List<StatisVo> aueryConditionTheme() {
       return this.getStatsVOList("themeId","themeName","themeGroup");

    }

    @Override
    public Page query(StrategySearchQuery qo) {
        TermQueryBuilder query = null;
        PageRequest of = PageRequest.of(qo.getCurrentPage()-1,qo.getPageSize(), Sort.Direction.DESC,qo.getOrderBy());

        if (qo.getType() == StrategySearchQuery.CONDITION_TYPE_COUNTRY){
            //国家
            query = QueryBuilders.termQuery("countryId",qo.getTypeValue());
        }else if (qo.getType() == StrategySearchQuery.CONDITION_TYPE_PROVINCE){
            query = QueryBuilders.termQuery("provinceId",qo.getTypeValue());
        }else if (qo.getType()==StrategySearchQuery.CONDITION_TYPE_THEME){
            query = QueryBuilders.termQuery("themeId",qo.getTypeValue());
        }
        if (query == null){
            return repository.findAll(of);
        }else {
            return repository.search(query,of);
        }

    }

    @Override
    public List<StrategyTemplate> findByDestName(String destName) {
        return repository.findByDestName(destName);
    }


    //通过主题id 查询目的地集合
    private List<StatisVo> getDestByThemeId(Long themeId) {
        ArrayList<StatisVo> vos = new ArrayList<>();
        List<StrategyTemplate>templates= repository.findByThemeId(themeId);
        //优化3 目的地去除重复
        ArrayList<String> list = new ArrayList<>();
        //广州  广州 广州


        for (StrategyTemplate template:templates) {
            if (!list.contains(template.getDestName())) {
                StatisVo vo = new StatisVo();
                vo.setId(template.getId());
                vo.setName(template.getDestName());
                vos.add(vo);
                list.add(template.getDestName());
            }
        }

        return vos;

    }

    //统计分组集合
    private List<StatisVo> getStatsVOList(String idField,String nameField,String groupName){

        List<Map<String,Object>> data = new ArrayList<>();

        //1 通过es分组查询 查询到主题类表
        List<CompositeValuesSourceBuilder<?>> sources = new ArrayList<>();//分组列对象集合
        TermsValuesSourceBuilder idSource = new TermsValuesSourceBuilder("id");
        idSource.field(idField);
        TermsValuesSourceBuilder nameSource = new TermsValuesSourceBuilder("name");
        nameSource.field(nameField);
        sources.add(idSource);
        sources.add(nameSource);


        //构造分组语法
        CompositeAggregationBuilder aggregationBuilder =new CompositeAggregationBuilder(groupName,sources);
        //查询语句构建类
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        builder.addAggregation(aggregationBuilder);
        //分页
        builder.withPageable(PageRequest.of(0,1));
        //明确指定查那个索引  那个库
        builder.withIndices(StrategyTemplate.INDEX_NAME);
        builder.withTypes(StrategyTemplate.TYPE_NAME);

        //执行查询语句  返回的结果
        AggregatedPage<StrategyTemplate> search = (AggregatedPage<StrategyTemplate>) repository.search(builder.build());

        InternalComposite themeGroup = search.getAggregations().get(groupName);

        ArrayList<StatisVo> list = new ArrayList<>();
        for (CompositeAggregation.Bucket bucket: themeGroup.getBuckets()){
            Long id= Long.parseLong(bucket.getKey().get("id").toString());
            String name = bucket.getKey().get("name").toString();
            Long count = bucket.getDocCount();

            StatisVo vo = new StatisVo();
            vo.setCount(count);
            vo.setId(id);
            vo.setName(name);
            list.add(vo);
        }
        //优化  1 排序  -----list集合排序
        Collections.sort(list, new Comparator<StatisVo>() {
            @Override
            public int compare(StatisVo o1, StatisVo o2) {
                //倒序排
                Long ret = o2.getCount()-o1.getCount();
                return ret.intValue();
            }
        });
        return list;

    }
}
